#include "command.h"

#define BUFFER_SIZE 1024

void compute_sha256_hash(const char *filename, char **hash_out) {
  FILE *file = fopen(filename, "rb");
  if (!file) {
    perror("Error opening file");
    return;
  }

  EVP_MD_CTX *mdctx = EVP_MD_CTX_new();  // 创建EVP_MD_CTX结构，用于哈希运算
  if (!mdctx) {
    fprintf(stderr, "Unable to create EVP_MD_CTX\n");
    fclose(file);
    return;
  }

  const EVP_MD *digest = EVP_sha256();  // 获取SHA-256哈希算法的指针
  if (!digest) {
    fprintf(stderr, "Unable to get SHA-256 digest\n");
    fclose(file);
    return;
  }

  unsigned char buffer[BUFFER_SIZE];  // 读取文件的缓冲区
  int bytes_read;
  unsigned char hash[EVP_MAX_MD_SIZE];  // 存储最终哈希值的数组
  unsigned int hash_len;                // 哈希值的长度

  if (EVP_DigestInit_ex(mdctx, digest, NULL) != 1) {
    fprintf(stderr, "Digest init failed\n");
    EVP_MD_CTX_free(mdctx);
    fclose(file);
    return;
  }

  // 循环读取文件内容，并更新摘要
  while ((bytes_read = fread(buffer, 1, BUFFER_SIZE, file)) > 0) {
    if (EVP_DigestUpdate(mdctx, buffer, bytes_read) != 1) {
      fprintf(stderr, "Digest update failed\n");
      EVP_MD_CTX_free(mdctx);
      fclose(file);
      return;
    }
  }

  // 最终计算摘要
  if (EVP_DigestFinal_ex(mdctx, hash, &hash_len) != 1) {
    EVP_MD_CTX_free(mdctx);
    fclose(file);
    return;
  }

  EVP_MD_CTX_free(mdctx);
  fclose(file);

  // 为哈希字符串分配内存
  *hash_out = malloc(hash_len * 2 + 1);  // 每个字节转为两个十六进制字符，加上空字符
  if (*hash_out == NULL) {
    fprintf(stderr, "为哈希字符串分配内存失败\n");
    return;
  }

  // 将哈希值转换为十六进制字符串
  char temp[3];  // 临时缓冲区，存储两个十六进制字符和空字符
  temp[2] = '\0';
  (*hash_out)[0] = '\0';  // 初始化字符串
  for (unsigned int i = 0; i < hash_len; i++) {
    snprintf(temp, sizeof(temp), "%02x", hash[i]);
    strcat(*hash_out, temp);  // 将转换后的十六进制字符串拼接到输出字符串
  }
}
